package exp07gui.tictactoe2;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class TicTacToe extends JFrame implements ActionListener {
    static Random random = new Random();

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        new TicTacToe();
    }

    final static String X = "X";
    final static String O = "O";
    final static String E = " ";
    final static int EE = 2;
    final static int XX = 0;
    final static int OO = 1;
    int computer;
    int player;
    int turn = 0;
    int B[][] = new int[3][3];
    JButton[] btn = new JButton[9];

    public TicTacToe() {
        turn = 0;
        player = turn;
        computer = 1 - turn;
        this.setLayout(new GridLayout(3, 3));
        for (int i = 0; i < 9; i++) {
            this.add(btn[i] = new JButton());
            btn[i].addActionListener(this);
        }
        for (int i = 0; i < 9; i++)
            B[i / 3][i % 3] = EE;
        this.setSize(300, 300);
        this.setVisible(true);

    }

    @Override
    public void actionPerformed(ActionEvent e) {

        for (int i = 0; i < 9; i++) {
            if (e.getSource() == btn[i]) {

                btn[i].setText("X");

                B[i / 3][i % 3] = player;

                btn[i].setEnabled(false);

                if (checkWin(OO)) {
                    JOptionPane.showMessageDialog(null, "O Win!");
                    resetGame();
                    return;

                } else if (checkWin(XX)) {
                    JOptionPane.showMessageDialog(null, "X Win!");
                    resetGame();
                    return;

                } else if (checkEnd()) {
                    JOptionPane.showMessageDialog(null, "Draw");
                    resetGame();
                    return;
                }
                //computerRun();
                greedySearch();
                break;
            }
        }
    }

    private boolean checkEnd() {
        for (int i = 0; i < 9; i++)
            if (B[i / 3][i % 3] == EE)
                return false;
        return true;
    }

    private void computerRun() {

        int x, y;
        while (true) {
            x = random.nextInt(3);
            y = random.nextInt(3);
            if (B[x][y] == EE) {
                break;
            }
        }
        B[x][y] = computer;
        btn[x * 3 + y].setText("O");
        btn[x * 3 + y].setEnabled(false);

    }

    private void greedySearch() {

        int x = 0, y = 0, maxValue = Integer.MIN_VALUE;
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++) {
                if (fvalue(i, j) > maxValue) {
                    x = i;
                    y = j;
                    maxValue = fvalue(i, j);
                }
            }
        JOptionPane.showMessageDialog(null, String.format("%d %d %d", x, y, maxValue));
        B[x][y] = computer;
        btn[x * 3 + y].setText("O");
        btn[x * 3 + y].setEnabled(false);

    }

    private int fvalue(int x, int y) {
        if (B[x][y] != EE)
            return -1;
        if (canWin(x, y, computer))
            return Integer.MAX_VALUE;
        if (canWin(x, y, player))
            return 50000;
        int s = 0;
        if (x == 1 && y == 1)
            s += 2000;
        if (x == y)
            s += 1000;
        if (x + y == 2)
            s += 1000;
        return s;
    }

    private boolean canWin(int x, int y, int p) {
        B[x][y] = p;
        if (checkWin(p)) {
            B[x][y] = EE;
            return true;
        } else {
            B[x][y] = EE;

            return false;
        }
    }

    private void resetGame() {
        for (int i = 0; i < 9; i++) {
            B[i / 3][i % 3] = EE;
            btn[i].setText(E);
            btn[i].setEnabled(true);

        }

    }

    private boolean checkWin(int x) {
        for (int i = 0; i < 3; i++)
            if (B[i][0] == x && B[i][1] == x && B[i][2] == x)
                return true;
        for (int i = 0; i < 3; i++)
            if (B[0][i] == x && B[1][i] == x && B[2][i] == x)
                return true;
        if (B[0][0] == x && B[1][1] == x && B[2][2] == x)
            return true;
        return B[0][2] == x && B[1][1] == x && B[2][0] == x;

    }

}
